#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "subwidget1.h"
#include "subwidget2.h"
#include "subwidget_serial.h"
#include "mythreadforsubwidget1.h"
#include "mythreadforsql.h"
#include "mythreadforserial.h"
#include "motor.h"
#include "util.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QNetworkProxy>
bool g_isMysqlOpen = false;
int g_SaveFrame = 10;
bool g_isAuto = false;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)        //这里new了一个MainWindow对象，并传给了私有属性ui
{
    ui->setupUi(this);

    setWindowTitle("粮食烘干系统");
    //限制只输入数字
    ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[0-9]+$")));
//    ui->lineEdit_ip->setValidator(new QRegExpValidator(QRegExp("[0-9]{3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}")));
//    ui->lineEdit_port->setValidator(new QRegExpValidator(QRegExp("[0-9]{4}")));

    //建立数据库连接
    m_db = QSqlDatabase::addDatabase("QMYSQL");  //采用QSQLITE数据库，QMYSQL数据库有问题？
    m_db.setHostName("localhost"); //设置数据库主机名
    m_db.setDatabaseName("mysql"); //设置数据库名   --数据库名是mysql，而我们的数据是在表managesystem1中
    m_db.setUserName("root"); //设置数据库登入用户名
    m_db.setPassword("267518"); //设计数据库登入密码
    m_db.open();          //打开数据库
    qDebug()<<QSqlDatabase::drivers();
    if(m_db.open())
    {
        qDebug()<<"open database success";
    }
    else
    {
        QMessageBox::warning(this,"error", "error open database", QMessageBox::Ok);
    }

   //addSubWindow传入一个widget返回值是QMdiSubWindow类型的，也就是帮我们创建一个subWindow，且下面的setActiveSubWindow传入的m_w1也是一个subWindow
    m_w3_Serial = new SubWidget_Serial;
//    m_w1 = ui->mdiArea->addSubWindow(new SubWidget1(m_db, *m_w3_Serial));  //先把thread1创建出来，最后添加到subWindow中
//    m_w2 = ui->mdiArea->addSubWindow(new SubWidget2(m_db, NUM_OF_SENSOR));

    m_thread_sql = new MyThreadForSql(m_db, NUM_OF_SENSOR);
    m_thread_sql->start();
    m_w2_test = new SubWidget2(m_db);
//    m_w2_test->show();
    m_w1_test = new SubWidget1(m_db, *m_w3_Serial);
//    m_w1_test->show();
    connect(m_w2_test, SIGNAL(sql_by_dataTime(QStringList)), m_thread_sql, SLOT(query_by_datatime(QStringList)));
    connect(m_thread_sql, &MyThreadForSql::refresh_vector, m_w2_test,
            [=]()
            {
               m_w2_test->updata_vector(0, m_thread_sql->getSequence(0));    //更新日期
               for(int i=1; i<NUM_OF_SENSOR;i++)
               {
                   //m_w2_test->updata_vector(i, m_thread_sql->getSequence<QVector<double>>(i));
                   m_w2_test->updata_vector(i, m_thread_sql->getSequence(i));
               }
               m_w2_test->plot_all_chart();
            });
    m_thread_Serial = new MyThreadForSerial();
    m_thread_Serial->start();
//    m_thread_Serial->show();
    m_motor = new Motor();
//    m_motor->show();
    connect(&(m_thread_Serial->get()), SIGNAL(get_data(int, double)), m_w1_test, SLOT(test_to_use_TimeData_Update(int, double)));
    connect(&(m_thread_Serial->get()), SIGNAL(push_to_sql(double, double)), m_thread_sql, SLOT(update_to_sql(double, double)));
    connect(m_motor, SIGNAL(motor2sensor(QByteArray, QString)), &(m_thread_Serial->get()), SLOT(slot_send_message(QByteArray, QString)));
    //对于css样式的设置，一定要在m_w1、m_w2和m_w3建立对象之后才行
    qss_style(*this, "./qrc/MainWindow.qss");             //为当前的MainWindow添加样式
    qss_style(*m_w1_test, "./qrc/subwidget1.qss");
    qss_style(*m_w2_test, "./qrc/subwidget1.qss");
    qss_style(*m_w3_Serial, "./qrc/subwidget1.qss");
    qss_style(*m_motor, "./qrc/subwidget1.qss");
    //tcp初始化
    tcpsocket = new QTcpSocket(this);
    tcpsocket->setProxy(QNetworkProxy::NoProxy);    //设置socket不走代理(如果开着翻墙软件，会连接不上server)
    //socket相关槽
    connect(&(m_thread_Serial->get()), SIGNAL(get_data(int, double)), this, SLOT(socket_write_SLOT(int, double)));

    //读写配置文件
    //读写ip port
    Util::get().readString("./json_rc/network.json", "server_ip", m_ip);
    Util::get().readDouble("./json_rc/network.json", "port", m_port);
    ui->lineEdit_ip->setText(m_ip);
    ui->lineEdit_port->setText(QString("%1").arg(m_port));
    qDebug()<<m_ip<<QString("   %1").arg(m_port);
    //读写设备信息
    QJsonArray infoAll;
    if(Util::get().readArray("./json_rc/equipmentInfo.json", "info", infoAll))
    {
        qDebug()<<"一次尝试  "<<infoAll[0];
    }
    for(int i=0;i<infoAll.size();i++)
    {
        m_equipmentInfo.push_back(infoAll[i].toDouble());
    }
    refreshComboBoxRemoveSensorType();
}

MainWindow::~MainWindow()
{
    delete ui;
    //程序执行结束后，统一将配置写入文件
    QJsonArray t_arr;
    Util::get().vector2QjsonArray(m_equipmentInfo, t_arr);
    Util::get().writeArray("./json_rc/equipmentInfo.json", "info", t_arr);
//    delete m_w1;                        //因为其储存的东西都是在这里new的，所以都要从这里删掉，而且其他地方都是传引用，所以能让他们删，得我们自己删
//    delete m_w2;
    delete m_w3_Serial;
//    delete m_thread_w1;
//    delete m_thread_w2;
    m_db.close();                       //断开数据库的连接
}

void MainWindow::on_actionw1_triggered()
{
//    MyThreadForSubwidget1 thread1;
//    thread1.start();
//    m_thread_w1 = new MyThreadForSubwidget1(m_db, *m_w3_Serial);            //要是在这里创建一个局部线程，程序一结束，就会死掉
//    m_thread_w1->start();
    m_w1_test->show();
//    ui->mdiArea->setActiveSubWindow(m_w1);
//    m_w1->show();
}

void MainWindow::on_actionw2_triggered()
{
//    ui->mdiArea->setActiveSubWindow(m_w2);
//    m_w2->show();
    m_w2_test->show();
}

void MainWindow::on_action_serial_triggered()
{
    m_thread_Serial->show();
    m_motor->show();
}

/**
 * @brief MainWindow::qss_style
 * @param w 这里变量a的类型暂时用m_w1、m_w2、m_w3_Serial共同的父类来作为容器存储，其实我们的a也就是一个容器，存了变量的引用
 * @param path qss文件的路径
 */
void MainWindow::qss_style(QWidget &w, QString path)
{
    QFile file(path);
    if(file.open(QFile::ReadOnly))                 //打开文件-以只读的方式
    {
        QString styleSheet = tr(file.readAll());    //读文件内容，并转为QString
        qDebug()<<"3333333333333333";
        //qDebug()<<styleSheet;
        w.setStyleSheet(styleSheet);
        file.close();
    }
    else
    {
        QMessageBox::warning(NULL, "warning", "Open failed", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
    }
}


void MainWindow::on_radioButton_clicked()
{
    g_isMysqlOpen = !g_isMysqlOpen;
    if(g_isMysqlOpen)
    {
        ui->label_showMessage->setText("开始保存至数据库...");
    }
    else
    {
        ui->label_showMessage->setText("关闭数据库...");
    }
    qDebug()<< "clicked:  " <<g_isMysqlOpen;
}


void MainWindow::on_pushButton_clicked()
{
    if(!g_isMysqlOpen)
    {
        QMessageBox::warning(this,"error","请先上方点击保存按钮，允许保存数据到数据库");
        ui->label_showMessage->setText("未开启数据库...");
        return ;
    }
    g_SaveFrame = ui->lineEdit->text().toInt();
    ui->label_showMessage->setText(QString("每%1s存储一次...").arg(g_SaveFrame));
    qDebug()<<"开始保存 "<<g_SaveFrame;
}

void MainWindow::socket_write_SLOT(int index, double data)
{
    if(tcpsocket->isWritable()) //貌似isOpen也可以，但是还是选用这个妥当
    {
        //const char* pStr = QString("传感器%1，数据:%2").arg(index).arg(data).toStdString().c_str();
        //tcpsocket->write(pStr);
        tcpsocket->write(QString("传感器%1，数据:%2").arg(index).arg(data).toStdString().c_str());
    }
}

void MainWindow::on_pushButton_socket_clicked()
{
    g_isAuto = !g_isAuto;
    //打开客服端
    if(g_isAuto)
    {
        tcpsocket->connectToHost(QHostAddress(QString(m_ip)), m_port);
        //超时说明连接失败
        if(!tcpsocket->waitForConnected(3000))
        {
            QMessageBox::information(this, "QT网络通信", "连接服务端失败！");
            ui->label_showMessage->setText("连接超时...");
            g_isAuto = !g_isAuto;
            return;
        }
        ui->pushButton_socket->setText("断开");   //自动模式其实就是是否选择与后端连接
        ui->label_showMessage->setText("连接服务器成功...");
        tcpsocket->write("登陆用户:gt；密码:111");      //可以用于当做密码，验证用
    }
    else //关闭客户端
    {
        tcpsocket->write("用户gt断开连接");
        tcpsocket->close();
        ui->pushButton_socket->setText("连接");
        ui->label_showMessage->setText("断开服务器连接...");
    }
    qDebug()<<"自动模式开启1 "<<g_isAuto;
}

bool MainWindow::tryMatch(std::string str, std::string pattern, std::smatch& results)
{
    // 规则
    std::regex r(pattern);
    // 匹配，并将结果匹配到results
    std::regex_search(str, results, r);
    qDebug()<<"daxiao  "<<results.length();
    return !results.empty();
}

void MainWindow::on_pushButton_2_clicked()
{
    if(g_isAuto)
    {
        QMessageBox::warning(this, "error", "请先断开连接!");
        return ;
    }
    //判断输入是否正确
    std::smatch results1, result2;
    if(tryMatch(ui->lineEdit_ip->text().toStdString(), "[0-9]{3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$", results1)
            &&
        tryMatch(ui->lineEdit_port->text().toStdString(), "[0-9]{3,5}", result2))
    {
        m_ip = ui->lineEdit_ip->text();
        m_port = ui->lineEdit_port->text().toDouble();
        Util::get().writeString("./json_rc/network.json", "server_ip", m_ip);
        Util::get().writeDouble("./json_rc/network.json", "port", m_port);
        ui->label_showMessage->setText(QString("ip:"+m_ip+QString(" port:%1").arg(m_port)+" 更新成功！"));
        //Util()::get().write
    }
    else
    {
        ui->lineEdit_ip->setText(m_ip);
        ui->lineEdit_port->setText(QString("%1").arg(m_port));
        QMessageBox::warning(this, "error", "输入有误，请按照之前格式!");
        return ;
    }

}


void MainWindow::on_pushButton_removeSensor_clicked()
{


    if(QMessageBox::No == QMessageBox::question(this, "warning", "确定要移除该设备?"))
    {
        qDebug()<<"哈哈，开玩笑，不移除";
        return;
    }
    qDebug()<<"开始移除";
    m_equipmentInfo.erase(m_equipmentInfo.begin()+ui->comboBox_removeSensorType->currentIndex());
    refreshComboBoxRemoveSensorType();
}

bool MainWindow::refreshComboBoxRemoveSensorType()
{
    ui->comboBox_removeSensorType->clear();
    for(int temp:m_equipmentInfo)
    {
        int addr = temp/100;
        int type = temp%10;
        switch(type)
        {
            case 0:ui->comboBox_removeSensorType->addItem(QString("设备%1--电机").arg(addr));break;
            case 1:ui->comboBox_removeSensorType->addItem(QString("设备%1--水分传感器").arg(addr));break;
            case 2:ui->comboBox_removeSensorType->addItem(QString("设备%1--温度传感器").arg(addr));break;
        }
    }
    return true;
}

void MainWindow::on_pushButton_addSensor_clicked()
{
    std::smatch result;
    if(!tryMatch(ui->lineEdit_addr->text().toStdString(), "[0-9]{1,2}", result))
    {
        QMessageBox::warning(this, "error", "输入格式错误!");
    }
    double info = ui->lineEdit_addr->text().toDouble();
    for(double t:m_equipmentInfo)
    {
        if(info==(int)t/100)
        {
            QMessageBox::warning(this, "error", "设备地址已占用!");
            return ;
        }
    }
    switch(ui->comboBox_addSensorType->currentIndex())
    {
        case 0:info = info*100+0;break;
        case 1:info = info*100+1;break;
        case 2:info = info*100+2;break;
        default:
            qDebug()<<"出现异常";
        break;
    }
    if(QMessageBox::No == QMessageBox::question(this, "warning", QString("确定要添加设备%1?").arg((int)info/100)))
    {
        qDebug()<<"先不添加";
        return;
    }
    m_equipmentInfo.push_back(info);
    qDebug()<<"添加成功";
    //Util::get().writeArray();   //向配置文件写数据
    refreshComboBoxRemoveSensorType();
}

/**
 * @brief MainWindow::on_pushButton_addSensor_clicked
 * 这个版本搞复杂了，这个版本是直接生产一个请求的数据帧，现在还不用这样
 */
//void MainWindow::on_pushButton_addSensor_clicked()
//{
//    std::smatch result;
//    if(tryMatch(ui->lineEdit_addr->text().toStdString(), "[0-9]{1,2}", result))
//    {
//        std::vector<char> addr;
//        addr.push_back((char)(ui->lineEdit_addr->text().toDouble()));
//        QByteArray add_sensor;
//        switch(ui->comboBox_addSensorType->currentIndex())
//        {
//            case 0:add_sensor = Util::get().read_json("./json_rc/sensor.json", "start");break;
//            case 1:add_sensor = Util::get().read_json("./json_rc/sensor.json", "sensor_th1");break;
//            case 2:qDebug()<<"2222";break;
//            default:
//                qDebug()<<"出现异常";
//            break;
//        }
//        int i=0;
//        for(char _t:add_sensor)
//        {
//            if(i!=0)
//            {
//                addr.push_back(_t);
//                i++;
//            }
//        }
//        m_addr.push_back(addr);
//    }
//}

